import gleam/int
import gleam/io

pub fn stage3_test() -> Int {
  // Tuple
  let triple = #(1, 1.22, "fucker fucker")
  io.debug(triple)
  // match of tuple
  let #(a, _, _) = triple
  io.debug(a)
  io.debug(triple.1)
  io.debug(weather(Spring))

  let teacher1 = Teacher("Mr Joe", "Physics")
  let student1 = Student("Hash")
  let school = [teacher1, student1]
  io.debug(school)
  io.debug(teacher1.name)
  io.debug(student1.name)

  let sf = Starfish("starfish", "Pink")
  case sf {
    Starfish(_, color) -> io.debug(color)
    Jellyfish(name, ..) -> io.debug(name)
  }

  let name: Option(String) = Some("fucker fucker")
  let name = None
  let level: Option(Int) = Some(10)
  let level = None

  return_nil()

  let x = Nil
  // Nil is unit type, view it as void
  io.debug(x)

  // let y : List(String )  = Nil
  let result = io.println("hello ")
  io.debug(result == Nil)

  // Results
  let _ = io.debug(buy_pastry(10))
  let _ = io.debug(buy_pastry(8))
  let _ = io.debug(buy_pastry(5))
  let _ = io.debug(buy_pastry(3))

  3
}

pub fn todo_without_reason() {
  // when It is todo, can not be called
  todo
}

pub fn todo_with_desc() {
  todo as "fucker will fuck you"
}

pub type PurchaseError {
  NotEnoughMoney(required: Int)
  NotLuckyEnough
}

fn buy_pastry(money: Int) -> Result(Int, PurchaseError) {
  case money >= 5 {
    True ->
      case int.random(4) == 0 {
        True -> Error(NotLuckyEnough)
        False -> Ok(money - 5)
      }
    False -> Error(NotEnoughMoney(required: 5))
  }
}

fn return_nil() -> Nil {
  Nil
}

// Generic
pub type Option(inner) {
  Some(inner)
  None
}

pub type Fish {
  Starfish(name: String, color: String)
  Jellyfish(name: String, jiggly: Bool)
}

pub type SchoolPerson {
  Teacher(name: String, subject: String)
  Student(name: String)
}

fn weather(season: Season) -> String {
  case season {
    Spring -> "Mild"
    Summer -> "Hot"
    Autumn -> "Windy"
    Winter -> "Cold"
  }
}

pub type Season {
  Spring
  Summer
  Autumn
  Winter
}
